package org.qphoto;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

public class TakePhotoActivity extends Activity implements
		SurfaceHolder.Callback {
	/** Called when the activity is first created. */

	public static String TAG             = "HIPPO_DEBUG";
	public static int MAX_PICS           = 12;
	public static int ROW_MAX_ITEM       = 3;
	public static int ROW_ITEM_INTERVAL  = 20;
	public static int TIME_INTERVAL      = 2000 / MAX_PICS;
	
	private SurfaceView mSurfaceView     = null;
	private SurfaceHolder mSurfaceHolder = null;
	private Camera mCamera               = null;
	private boolean mIsCameraValide      = false;
	private View mToolButtonsView        = null;
	private View mProgressView           = null;
	private Button mActionButton         = null;
	private ProgressBar mActionProgress  = null;
	private int mPicCount                = 0;
	private int mPostPicCount            = 0;
	private boolean mIsPreviewPhoto      = true;  
	DisplayMetrics dm   = null; 
	String sdcardpath   = null; 
	String tmpimagepath = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.takephoto);


		dm = new DisplayMetrics(); 
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		
		tmpimagepath = CoreData.getCoreData().getImpImagePath();

		
		mSurfaceView = (SurfaceView) findViewById(R.id.cameraSurfaceView);

		mSurfaceHolder = mSurfaceView.getHolder();
		mSurfaceHolder.addCallback(this);

		
		mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

		
		mActionButton    = (Button) findViewById(R.id.action);
		mProgressView    = findViewById(R.id.progressview);
		mToolButtonsView = findViewById(R.id.toolbuttonsview);
		mActionProgress  = (ProgressBar) findViewById(R.id.actionprogress);

		mActionButton.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mToolButtonsView.setVisibility(View.INVISIBLE);
				mProgressView.setVisibility(View.VISIBLE);

				if (mCamera != null) {
					takePicture();
					handler.postDelayed(runnable, TIME_INTERVAL);
				}
			}
		});

	}

	@Override
	public void onPause() {
		super.onPause();
		resetCamera();
	}

	@Override
	public void onResume() {
		super.onResume();
		
		if ( mPicCount == MAX_PICS && mPostPicCount >= MAX_PICS)
		{
			mPicCount     = 0;
			mPostPicCount = 0;
			mToolButtonsView.setVisibility(View.VISIBLE);
			mProgressView.setVisibility(View.INVISIBLE);
		}
		//initCamera();
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		resetCamera();
	}

	Handler handler = new Handler();
	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			takePicture();
		}
	};
	
	Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
		public void onPreviewFrame(byte[] data, Camera camera) {
			Log.d(TAG, "onPictureTaken - raw");
			
			getPreviewPicture(data,camera);
		}
	};
	
	/** Handles data for jpeg picture */
	PictureCallback jpegCallback = new PictureCallback() {
		public void onPictureTaken(byte[] data, Camera camera) {
			Log.d(TAG, "onPictureTaken - jpeg");
			
			
		    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 
		    covertAndSaveBitmap(bitmap);
		    
			mPicCount++;
			mCamera.startPreview();
		}
	};
	
	private void takePicture()
	{
		if (mPicCount < MAX_PICS && mPostPicCount == mPicCount) {
			if( this.mIsPreviewPhoto == false)
			{
				mCamera.takePicture(null,null,null,jpegCallback);
			} else {
				mCamera.setOneShotPreviewCallback (previewCallback); 
			}
			
			mPostPicCount = mPicCount+1;
			mActionProgress.setMax(MAX_PICS);
			mActionProgress.setProgress(mPostPicCount);
		} 

		if (mPicCount >= MAX_PICS) {
			handler.removeCallbacks(runnable);
			
			// goto next activity
			gotoNextActivity();
		} else {
			
			handler.postDelayed(runnable, TIME_INTERVAL);
		}
	}
	
	public void gotoNextActivity()
	{
		Intent intent = new Intent(); 
		intent.setClass(TakePhotoActivity.this,SelectImagesActivity.class);
		
		
		Bundle bundle = new Bundle();
		bundle.putInt("photonum",this.mPicCount);
		bundle.putString("tmpimagepath",this.tmpimagepath);
		
		
        intent.putExtras(bundle); 
        
        startActivity(intent); 
	}
	
	
	private boolean covertAndSaveBitmap(Bitmap orginal_bmp)
	{
	    Bitmap tempBitmap    = orginal_bmp;
	    int    tempW         = tempBitmap.getWidth();
	    int    tempH         = tempBitmap.getHeight();
	    Matrix mtx           = new Matrix();
	    mtx.postRotate(90);
	    orginal_bmp   = Bitmap.createBitmap(tempBitmap, 0,0,tempW, tempH, mtx, true);
	    tempBitmap.recycle();
	    
	    int orginal_width    = orginal_bmp.getWidth();
	    int orginal_height   = orginal_bmp.getHeight();
	    
	    int to_width         = (dm.widthPixels - 30 - (ROW_MAX_ITEM-1)*ROW_ITEM_INTERVAL)/ROW_MAX_ITEM;
	    int to_height        = to_width*orginal_height/orginal_width;
	    Bitmap thumbnail_bmp = Bitmap.createScaledBitmap(orginal_bmp, to_width, to_height, false);
	     
	    String orginal_pic   = tmpimagepath + "/" + mPicCount + ".jpg";
	    String thumbnail_pic = tmpimagepath + "/" + mPicCount + "_nail.jpg";
	    
	   
	    boolean bsaveorg  = saveBitmapToFile(orginal_bmp,orginal_pic);
	    boolean bsavenail = saveBitmapToFile(thumbnail_bmp,thumbnail_pic);

	    
	    orginal_bmp.recycle();
	    thumbnail_bmp.recycle();
	    
	    return bsaveorg&&bsavenail;
	}
	
	private void getPreviewPicture(byte[] data,Camera camera)
	{
		
		Camera.Parameters parameters = camera.getParameters();
        int imageFormat = parameters.getPreviewFormat();
        Bitmap bitmap   = null;

        if ( imageFormat == ImageFormat.NV21 )
        {
            int w = parameters.getPreviewSize().width;
            int h = parameters.getPreviewSize().height;
            YuvImage yuvImage = new YuvImage( data, imageFormat, w, h, null );
            Rect rect = new Rect( 0, 0, w, h );
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            yuvImage.compressToJpeg( rect, 100, outputStream );

            bitmap = BitmapFactory.decodeByteArray( outputStream.toByteArray(), 0, outputStream.size() );
        }
        else if ( imageFormat == ImageFormat.JPEG || imageFormat == ImageFormat.RGB_565 )
        {
            bitmap = BitmapFactory.decodeByteArray( data, 0, data.length );
        }
		
        if (bitmap == null)
        	return;
        
        covertAndSaveBitmap(bitmap);
		
		
		mPicCount++;
		mCamera.setOneShotPreviewCallback(null); 
	}

	public void surfaceCreated(SurfaceHolder surfaceholder) {
		// TODO Auto-generated method stub
		Log.i(TAG, "Surface Changed2");
		initCamera();
	}

	private void initCamera()
    {
    	try {
			
			if ( mIsCameraValide == false)
    		{
				mCamera = Camera.open();
				
				mIsCameraValide = true;
    		}
			
			mCamera.setPreviewDisplay(mSurfaceHolder);
    	} catch (Exception e) {
			Toast.makeText(this,"can not init camera", Toast.LENGTH_LONG).show();
		}
    	
    	
    	mCamera.stopPreview();
    	
    	
		Camera.Parameters parameters = mCamera.getParameters();

		parameters.setPictureFormat(PixelFormat.JPEG);
		parameters.setJpegQuality(100);
		
		mCamera.setParameters(parameters);
		mCamera.setDisplayOrientation(90);

		mCamera.startPreview();
    }

	private void resetCamera() {
		if (mIsCameraValide == true) {
			mCamera.stopPreview();

			mCamera.release();
			mCamera = null;
		}
		mIsCameraValide = false;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
		// TODO Auto-generated method stub

		if (mIsCameraValide == true) {
			
			mCamera.stopPreview();

			
			Camera.Parameters parameters = mCamera.getParameters();

			
			parameters.setPreviewSize(w, h);

			
			mCamera.startPreview();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		resetCamera();
		Log.i(TAG, "Surface Destroyed");
	}
	
	
	public static boolean saveBitmapToFile(Bitmap bmp,String filepath)
	{
		
	      File myCaptureFile = new File(filepath);
	      try
	      {
	    	  BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
	    	  
	    	  bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
	        
	    	  
	    	  bos.flush();
	        
	    	  
	    	  bos.close();
	    	  
	    	  return true;
	      }
	      catch (Exception e)
	      {
	    	  Log.e(TAG, e.getMessage());
	    	  Log.e(TAG, e.toString());
	    	  return false;
	      }
	}
}